package com.hmdp.scheduled;

import com.hmdp.entity.MessageRecord;
import com.hmdp.service.MessageRecordService;
import com.hmdp.entity.MessageStatus;
import com.hmdp.annotion.ReliableMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class MessageRetryTask {
    
    @Autowired
    private MessageRecordService messageRecordService;
    @Autowired
    private ApplicationContext applicationContext;

    
    // 每30秒执行一次
    @Scheduled(fixedRate = 30000)
    public void retryFailedMessages() {
        List<MessageRecord> pendingMessages = messageRecordService.queryPendingMessages(100);
        
        for (MessageRecord message : pendingMessages) {
            try {
                ReliableMessage reliableMessage = getReliableMessageFromMetadata(message);
                
                // 检查是否达到最大重试次数
                if (message.getRetryCount() >= reliableMessage.maxRetry()) {
                    log.warn("消息已达到最大重试次数，不再重试，messageId: {}", message.getMessageId());
                    continue;
                }
                
                // 检查是否到达下次重试时间
                if (message.getNextRetryTime() != null && 
                    message.getNextRetryTime().after(new Date())) {
                    continue;
                }
                
                // 执行重试
                boolean success = remoteCall(
                    message.getServiceName(),
                    message.getMethodName(),
                    message.getParamsJson()
                );
                
                if (success) {
                    messageRecordService.updateStatus(message.getMessageId(), MessageStatus.SUCCESS);
                } else {
                    // 计算下次重试时间
                    int retryCount = message.getRetryCount() + 1;
                    Date nextRetryTime = calculateNextRetryTime(retryCount, reliableMessage.retryInterval());

                    //小于最大重试次数
                    if (retryCount <= message.getMaxRetry()) {
                        messageRecordService.updateForRetry(
                                message.getMessageId(),
                                retryCount,
                                nextRetryTime
                        );
                    }else{
                        messageRecordService.updateFail(
                                message.getMessageId(),
                                retryCount,
                                nextRetryTime);
                    }

                }
            } catch (Exception e) {
                log.error("重试消息失败，messageId: {}", message.getMessageId(), e);
            }
        }
    }
    
    private Date calculateNextRetryTime(int retryCount, long retryInterval) {
        // 可以使用指数退避算法
        long delay = retryInterval * 1000 * retryCount;
        return new Date(System.currentTimeMillis() + delay);
    }
    
    // 模拟远程调用
    private boolean remoteCall(String serviceName, String methodName, String paramsJson) {
        // 实际项目中可以使用Feign或其他RPC框架
        // 这里简化为随机成功/失败
        return Math.random() > 0.3; // 70%成功率
    }

    private ReliableMessage getReliableMessageFromMetadata(MessageRecord message) {
        try {
            Class<?> clazz = Class.forName(message.getClassName());
            Method method = Arrays.stream(clazz.getMethods())
                    .filter(m -> m.getName().equals(message.getOriginalMethodName()))
                    .findFirst()
                    .orElseThrow(() -> new Exception("异常信息"));

            return method.getAnnotation(ReliableMessage.class);
        } catch (Exception e) {
            log.error("获取原始注解失败，使用默认配置", e);
            return getReliableMessageFromMetadata_2(message);
        }
    }

    
    // 在实际项目中，需要从元数据中获取注解配置
    private ReliableMessage getReliableMessageFromMetadata_2(MessageRecord message) {
        // 这里简化实现，实际项目中可以通过反射或存储元数据获取
        return new ReliableMessage() {
            @Override
            public Class<? extends Annotation> annotationType() {
                return ReliableMessage.class;
            }

            @Override
            public String serviceName() {
                return message.getServiceName();
            }

            @Override
            public String methodName() {
                return message.getMethodName();
            }

            @Override
            public int maxRetry() {
                return 3; // 默认值
            }

            @Override
            public long retryInterval() {
                return 60; // 默认值
            }
        };
    }

    private ReliableMessage getFromSpringContext(MessageRecord message) throws Exception {
        Object bean = applicationContext.getBean(message.getServiceName());
        Method method = Arrays.stream(bean.getClass().getMethods())
                .filter(m -> m.getName().equals(message.getMethodName()))
                .findFirst()
                .orElseThrow(() -> new Exception("异常信息"));
        return method.getAnnotation(ReliableMessage.class);
    }
}